package com.ikingtech.platform.service.system.dict.service;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ikingtech.framework.sdk.base.model.PageResult;
import com.ikingtech.framework.sdk.context.security.Me;
import com.ikingtech.framework.sdk.context.exception.FrameworkException;
import com.ikingtech.framework.sdk.dict.model.DictItemQueryParamDTO;
import com.ikingtech.framework.sdk.utils.Tools;
import com.ikingtech.platform.service.system.dict.entity.DictItemDO;
import com.ikingtech.platform.service.system.dict.exception.DictExceptionInfo;
import com.ikingtech.platform.service.system.dict.mapper.DictItemMapper;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @author tie yan
 */
@Service
@AllArgsConstructor
public class DictItemService extends ServiceImpl<DictItemMapper, DictItemDO> {

    public String parseFullPath(String parentId, String id) {
        if (Tools.Str.isNotBlank(parentId)) {
            DictItemDO parentEntity = this.getById(parentId);
            if (null == parentEntity) {
                throw new FrameworkException(DictExceptionInfo.PARENT_DICT_ITEM_NOT_FOUND);
            }
            return parentEntity.getFullPath() + "@" + id;
        } else {
            return id;
        }
    }

    public List<DictItemDO> listByDictId(String dictId) {
        return this.list(Wrappers.<DictItemDO>lambdaQuery()
                .eq(DictItemDO::getDictId, dictId));
    }

    public void removeByDictId(String id) {
        this.remove(Wrappers.<DictItemDO>query().lambda()
                .eq(DictItemDO::getDictId, id)
                .eq(DictItemDO::getTenantCode, Me.tenantCode()));
    }

    public void removeByFullPath(String fullPath, String tenantCode) {
        this.remove(Wrappers.<DictItemDO>query().lambda()
                .likeRight(DictItemDO::getFullPath, fullPath)
                .eq(DictItemDO::getTenantCode, tenantCode));
    }

    public Boolean labelExist(String dictId, String label, String tenantCode) {
        return this.baseMapper.exists(Wrappers.<DictItemDO>lambdaQuery()
                .isNotNull(DictItemDO::getId)
                .eq(DictItemDO::getDictId, dictId)
                .eq(DictItemDO::getLabel, label)
                .eq(DictItemDO::getTenantCode, tenantCode));
    }

    public Boolean labelExist(String dictId, String id, String value, String tenantCode) {
        return this.baseMapper.exists(Wrappers.<DictItemDO>lambdaQuery()
                .ne(DictItemDO::getId, id)
                .eq(DictItemDO::getDictId, dictId)
                .eq(DictItemDO::getValue, value)
                .eq(DictItemDO::getTenantCode, tenantCode));
    }

    public PageResult<DictItemDO> listPage(DictItemQueryParamDTO queryParam, String tenantCode) {
        return PageResult.build(this.page(new Page<>(queryParam.getPage(), queryParam.getRows()), Wrappers.<DictItemDO>lambdaQuery()
                .eq(Tools.Str.isNotBlank(queryParam.getDictId()), DictItemDO::getDictId, queryParam.getDictId())
                .like(Tools.Str.isNotBlank(queryParam.getLabel()), DictItemDO::getLabel, queryParam.getLabel())
                .eq(Tools.Str.isNotBlank(queryParam.getValue()), DictItemDO::getValue, queryParam.getValue())
                .eq(null != queryParam.getPreset(), DictItemDO::getPreset, queryParam.getPreset())
                .eq(DictItemDO::getTenantCode, tenantCode)
                .orderByDesc(DictItemDO::getCreateTime)));
    }

    public Integer getMaxSortOrder(String parentId) {
        List<Number> orders = this.listObjs(Wrappers.<DictItemDO>query().lambda()
                .select(DictItemDO::getSortOrder)
                .eq(DictItemDO::getParentId, parentId)
                .eq(DictItemDO::getTenantCode, Me.tenantCode())
                .orderByDesc(DictItemDO::getSortOrder), Number.class::cast);
        return Tools.Coll.isBlank(orders) ? 0 : orders.get(0).intValue();
    }

    public List<DictItemDO> between(Object parentNodeId, Object startValue, Object endValue) {
        return this.list(Wrappers.<DictItemDO>query().lambda()
                .between(DictItemDO::getSortOrder, startValue, endValue)
                .eq(DictItemDO::getParentId, parentNodeId)
                .eq(DictItemDO::getTenantCode, Me.tenantCode())
        );
    }

    public List<DictItemDO> gt(Object parentNodeId, Object value) {
        return this.list(Wrappers.<DictItemDO>query().lambda()
                .eq(DictItemDO::getParentId, parentNodeId)
                .gt(DictItemDO::getSortOrder, value)
                .eq(DictItemDO::getTenantCode, Me.tenantCode())
        );
    }

    @Transactional(rollbackFor = Exception.class)
    public void updateChildrenPreset(Boolean preset, String fullPath, String tenantCode) {
        this.update(Wrappers.<DictItemDO>lambdaUpdate()
                .set(DictItemDO::getPreset, preset)
                .likeRight(DictItemDO::getFullPath, fullPath)
                .eq(DictItemDO::getTenantCode, tenantCode));
    }

    public void removeByTenantCode(String tenantCode) {
        this.remove(Wrappers.<DictItemDO>query().lambda()
                .eq(DictItemDO::getTenantCode, tenantCode));
    }

    public List<DictItemDO> listByTenantCode(String tenantCode) {
        return this.list(Wrappers.<DictItemDO>lambdaQuery()
                .eq(DictItemDO::getTenantCode, tenantCode)
                .orderByDesc(DictItemDO::getCreateTime));
    }

    public List<DictItemDO> listByDictCodes(List<String> dictCodes, String tenantCode) {
        return this.list(Wrappers.<DictItemDO>lambdaQuery()
                .eq(DictItemDO::getTenantCode, tenantCode)
                .in(DictItemDO::getDictCode, dictCodes));
    }
}
